package gdma.hqdes.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import gdma.hqdes.bean.HqdProject;
import gdma.hqdes.bean.Unit;
import gdma.hqdes.bean.UnitScore;
import gdma.hqdes.dao.HqdIndexMapper;
import gdma.hqdes.dao.HqdProjectMapper;
import gdma.hqdes.dao.UnitMapper;
import gdma.hqdes.dao.UnitScoreMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Nullable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author wangyue
 * @Version 3.0
 * @Date 2024-07-24
 */

@Service
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    HqdProjectMapper projectMapper;

    @Autowired
    HqdIndexMapper indexMapper;

    @Autowired
    UnitMapper unitMapper;

    @Autowired
    UnitScoreMapper unitScoreMapper;

    @Override
    public HqdProject getProject(long id) {
        return projectMapper.selectById(id);
    }

    @Override
    public HqdProject getProject(int year, int scope) {
        return projectMapper.selectByYearAndScope(year, scope);
    }

    @Override
    public List<HqdProject> getProjects(int year, int scope0) {
        if(scope0 < Unit.SCOPE_MUNICIPAL) scope0 = Unit.SCOPE_MUNICIPAL;
        return projectMapper.getProjects(year, scope0);
    }

    @Override
    public List<HqdProject> getActiveProjects(Date current, Integer scope0) {
        LambdaQueryWrapper<HqdProject> query = new LambdaQueryWrapper<>();
        if(current != null) {
            query.le(HqdProject::getStartTime, current);
            query.gt(HqdProject::getEndTime, current);
        }
        if(scope0 != null) {
            if(scope0 < Unit.SCOPE_MUNICIPAL) scope0 = Unit.SCOPE_MUNICIPAL;
            query.ge(HqdProject::getScope, scope0);
        }
        return projectMapper.selectList(query);
    }

    @Override
    public List<HqdProject> getProjectsByYear(int year) {
        return projectMapper.selectByYear(year);
    }

    @Override
    public List<HqdProject> listProjects(@Nullable Integer year0, @Nullable Integer year1, @Nullable Integer scope, @Nullable Integer scope0, @Nullable String name) {
        LambdaQueryWrapper<HqdProject> query = new LambdaQueryWrapper<>();
        if(year0 != null) query.ge(HqdProject::getYear, year0);
        if(year1 != null) query.le(HqdProject::getYear, year1);
        if(scope != null) query.eq(HqdProject::getScope, scope);
        if(scope0 != null) query.ge(HqdProject::getScope, scope0);
        if(StringUtils.hasText(name)) query.like(HqdProject::getName, name);
        return projectMapper.selectList(query);
    }

    @Override
    public HqdProject saveProject(HqdProject project) {
        if(project.getId() == null) {
            project.setCreatedTime(new Date());
            projectMapper.insert(project);
        } else {
            project.setUpdatedTime(new Date());
            projectMapper.updateById(project);
        }
        return project;
    }

    @Override
    public float updateProjectProgress(long id) {
        HqdProject project = projectMapper.selectById(id);
        if(project == null) return 0;
        List<Long> allUnitIds = unitMapper.getUnitIds(project.getScope());
        project.setParticipatedNum(allUnitIds.size());
        int indexNum = (int)indexMapper.selectByVerId(project.getIndexVerId()).stream().count();
        List<UnitScore> scores = unitScoreMapper.selectScores(project.getId());
        Map<Long, List<UnitScore>> all = scores.stream().collect(Collectors.groupingBy(UnitScore::getUnitId));

        List<Long> stage1FinishedUnitIds = all.entrySet().stream()
                .filter(kv -> kv.getValue().size() >= indexNum)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        int stage1FinishedNum = stage1FinishedUnitIds.size();
        project.setStage1FinishedNum(stage1FinishedNum);
        if(stage1FinishedNum < allUnitIds.size())
            project.setStage1Comment("未完成：" + makeStageComment(allUnitIds, stage1FinishedUnitIds, 5));
        else
            project.setStage1Comment("所有单位都已完成");

        project.setStage1FinishedNum(stage1FinishedNum);
        List<Long> stage2FinishedUnitIds = all.entrySet().stream()
                .filter(kv -> kv.getValue().stream().filter(s -> s.getStatus() != null && s.getStatus() == UnitScore.STATUS_APPROVED).count() >= indexNum)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        int stage2FinishedNum = stage2FinishedUnitIds.size();
        project.setStage2FinishedNum(stage2FinishedNum);
        if(stage2FinishedNum < allUnitIds.size())
            project.setStage2Comment("未完成：" + makeStageComment(allUnitIds, stage2FinishedUnitIds, 5));
        else
            project.setStage2Comment("所有单位都已完成");

        project.setUpdatedTime(new Date());
        projectMapper.updateById(project);
        return (float)project.getStage1FinishedNum() / (float)project.getParticipatedNum();
    }

    private String makeStageComment(List<Long> allUnitIds, List<Long> finishedUnitIds, int maxUnitNum) {
        List<Long> unfinishedUnitIds = allUnitIds.stream().filter(v -> !finishedUnitIds.contains(v)).collect(Collectors.toList());
        List<Unit> unfinishedUnits = unitMapper.selectBatchIds(unfinishedUnitIds);
        String stageComment = unfinishedUnits.subList(0, Math.min(unfinishedUnits.size(), maxUnitNum)).stream()
                .map(Unit::getShortName)
                .collect(Collectors.joining("、"));
        if(unfinishedUnits.size() > maxUnitNum) stageComment += " 等" + unfinishedUnits.size() + "个单位";
        return stageComment;
    }

}
